﻿using System;
using System.Collections.Generic;

using System.Text;
using System.Data;
using Efficient.Domain;
using Common.Logging;

namespace Efficient.DataAccess
{
    public static class ExtendDbService
    {
        private static readonly ILog logger = LogManager.GetLogger(typeof(ExtendDbService));
        /// <summary>
        /// 创建实体查询语句构造器
        /// </summary>
        /// <param name="dao"></param>
        /// <returns></returns>
        public static IEntityQueryBuilder GetEntityQueryBuilder(IDbService dao)
        {
            return new EntityQueryBuilder(dao);
        }

        public static IList<T> FindAllEntity<T>(IDbService dao, Reader2Entity<T> converter, IPagingInfo pagingInfo, params OrderField[] orderFields) where T : new()
        {
            IEntityQueryBuilder builder = dao.GetEntityQueryBuilder();
            IQuery query = dao.CreateQuery(builder.BuildQueryAll<T>(orderFields));
            return dao.DoListQuery<T>(converter, pagingInfo, query);
        }

        public static IList<T> FindAllEntity<T>(IDbService dao, IDbConnection conn, Reader2Entity<T> converter, IPagingInfo pagingInfo, params OrderField[] orderFields) where T : new()
        {
            IEntityQueryBuilder builder = dao.GetEntityQueryBuilder();
            IQuery query = dao.CreateQuery(conn, builder.BuildQueryAll<T>(orderFields));
            return dao.DoListQuery<T>(converter, pagingInfo, query);
        }

        public static IList<T> FindAllEntity<T>(IDbService dao, IDbTransaction tran, Reader2Entity<T> converter, IPagingInfo pagingInfo, params OrderField[] orderFields) where T : new()
        {
            IEntityQueryBuilder builder = dao.GetEntityQueryBuilder();
            IQuery query = dao.CreateQuery(tran, builder.BuildQueryAll<T>(orderFields));
            return dao.DoListQuery<T>(converter, pagingInfo, query);
        }

        public static IList<T> DoListQuery<T>(IDbService dao, Reader2Entity<T> converter, IPagingInfo pagingInfo, IQuery query) where T : new()
        {
            query.SetEntityConverter<T>(converter);
            if (pagingInfo != null && pagingInfo.IsLegal)
            {
                if (pagingInfo.DoCount)
                {
                    pagingInfo.RecordConut = query.ComputeRecordCount();
                }
                query.SetFirstResult((uint)(pagingInfo.CurrentPage * pagingInfo.PageSize));
                query.SetMaxResults((uint)(pagingInfo.PageSize));
            }
            return query.List<T>();
        }

        public static DataTable DoTableQuery(IDbService dao, IPagingInfo pagingInfo, IQuery query)
        {
            if (pagingInfo != null && pagingInfo.IsLegal)
            {
                if (pagingInfo.DoCount)
                {
                    pagingInfo.RecordConut = query.ComputeRecordCount();
                }
                query.SetFirstResult((uint)(pagingInfo.CurrentPage * pagingInfo.PageSize));
                query.SetMaxResults((uint)(pagingInfo.PageSize));
            }
            return query.Table();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dao"></param>
        /// <param name="tran"></param>
        /// <param name="converter"></param>
        /// <param name="keyword"></param>
        /// <param name="pagingInfo"></param>
        /// <param name="orderFields"></param>
        /// <returns></returns>
        public static IList<T> FindEntityByKeyword<T>(IDbService dao, IDbTransaction tran, Reader2Entity<T> converter, string keyword, IPagingInfo pagingInfo, params OrderField[] orderFields) where T : new()
        {
            IEntityQueryBuilder builder = dao.GetEntityQueryBuilder();
            KeywordQuery keywordQuery = builder.BuildQueryByKeyword<T>(orderFields);
            string queryString = string.IsNullOrEmpty(keyword) ? builder.BuildQueryAll<T>(orderFields) : keywordQuery.QueryString;
            IQuery query = dao.CreateQuery(tran, queryString);
            if (!string.IsNullOrEmpty(keyword))
            {
                keywordQuery.SetKeywordToQuery(query, keyword);
            }
            return dao.DoListQuery<T>(converter, pagingInfo, query);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dao"></param>
        /// <param name="conn"></param>
        /// <param name="converter"></param>
        /// <param name="keyword"></param>
        /// <param name="pagingInfo"></param>
        /// <param name="orderFields"></param>
        /// <returns></returns>
        public static IList<T> FindEntityByKeyword<T>(IDbService dao, IDbConnection conn, Reader2Entity<T> converter, string keyword, IPagingInfo pagingInfo, params OrderField[] orderFields) where T : new()
        {
            IEntityQueryBuilder builder = dao.GetEntityQueryBuilder();
            KeywordQuery keywordQuery = builder.BuildQueryByKeyword<T>(orderFields);
            string queryString = string.IsNullOrEmpty(keyword) ? builder.BuildQueryAll<T>(orderFields) : keywordQuery.QueryString;
            IQuery query = dao.CreateQuery(conn, queryString);
            if (!string.IsNullOrEmpty(keyword))
            {
                keywordQuery.SetKeywordToQuery(query, keyword);
            }
            return dao.DoListQuery<T>(converter, pagingInfo, query);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dao"></param>
        /// <param name="converter"></param>
        /// <param name="keyword"></param>
        /// <param name="pagingInfo"></param>
        /// <param name="orderFields"></param>
        /// <returns></returns>
        public static IList<T> FindEntityByKeyword<T>(IDbService dao, Reader2Entity<T> converter, string keyword, IPagingInfo pagingInfo, params OrderField[] orderFields) where T : new()
        {
            IEntityQueryBuilder builder = dao.GetEntityQueryBuilder();
            KeywordQuery keywordQuery = builder.BuildQueryByKeyword<T>(orderFields);
            string queryString = string.IsNullOrEmpty(keyword) ? builder.BuildQueryAll<T>(orderFields) : keywordQuery.QueryString;
            IQuery query = dao.CreateQuery(queryString);
            if (!string.IsNullOrEmpty(keyword))
            {
                keywordQuery.SetKeywordToQuery(query, keyword);
            }

            return dao.DoListQuery<T>(converter, pagingInfo, query);
        }

        /// <summary>
        /// 创建Hibernate风格的查询
        /// </summary>
        /// <param name="dao"></param>
        /// <param name="query">查询语句</param>
        /// <returns></returns>
        public static IQuery CreateQuery(IDbService dao, string query)
        {
            return new QueryImpl(dao, query);
        }

        /// <summary>
        /// 创建Hibernate风格的查询
        /// </summary>
        /// <param name="dao"></param>
        /// <param name="conn">已有的数据库连接</param>
        /// <param name="query">查询语句</param>
        /// <returns></returns>
        public static IQuery CreateQuery(IDbService dao, IDbConnection conn, string query)
        {
            return new QueryImpl(conn, dao, query);
        }

        /// <summary>
        /// 创建Hibernate风格的查询
        /// </summary>
        /// <param name="dao"></param>
        /// <param name="tran">已有的数据库事务</param>
        /// <param name="query">查询语句</param>
        /// <returns></returns>
        public static IQuery CreateQuery(IDbService dao, IDbTransaction tran, string query)
        {
            return new QueryImpl(tran, dao, query);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dao"></param>
        /// <param name="paramSet"></param>
        /// <returns></returns>
        public static IDbDataParameter[] ToDbParameter(IDbService dao, IEnumerable<IParameter> paramSet)
        {
            if(paramSet == null)
            {
                return new IDbDataParameter[0];
            }
            List<IDbDataParameter> result = new List<IDbDataParameter>();
            foreach (IParameter item in paramSet)
            { 
                result.Add(item.ToDbDataParameter(dao));
            }
            return result.ToArray();
        }

        public static string BuildOrderByString(IDbService dao, params OrderField[] orderBy)
        {
            if (orderBy == null || orderBy.Length == 0)
            {
                return string.Empty;
            }
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < orderBy.Length;i++ )
            {
                result.Append(orderBy[i]);
                if (i < orderBy.Length - 1)
                {
                    result.Append(",");
                }
            }
            return result.ToString();
        }
    }
}
